﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace ImCommon {
    // 结果码
    public enum ResultCode {
        ADD_FRIEND_ALLOW,               // "添加{0}为好友成功。"
        ADD_FRIEND_NOT_ALLOW,           // "拒绝和你成为好友。"
        ALREADY_BE_FRIENDS,             // "已经是你的好友了。"
        FRIEND_NAME_EQUAL_SELF_NAME,    // "好友名字与自己名字相同。"
        LOGON_SUCCEEDED,                // "登录成功。"
        NETWORK_ERROR,                  // "连接服务失败，请参考使用说明。"
        PASSWORD_WRONG,                 // "密码不正确。"
        REG_SUCCEEDED,                  // "注册成功。"
        SUCCEEDED,                      // ""
        TOO_MANY_FRIENDS,               // "朋友太多了，不能再继续添加了。"
        USER_ALREADY_LOGON,             // "该用户已经登录了。"
        USER_EXISTS,                    // "该用户名已经被注册了。"
        USER_NOT_FOUND                  // "该用户尚未注册。"
    }

    // 协议
    [Serializable]
    public class ImProtocol {
        // 类型
        public enum Type {
            ADD_FRIEND_REQUEST, // 添加好友请求
            ADD_FRIEND_RESULT,  // 添加好友结果
            CHAT,               // 聊天
            FRIEND_LOGON,       // 好友登录
            LOGOFF,             // 离线
            LOGON,              // 登录
            REG                 // 注册
        }
        
        public const string MULTI_CHAT = "群发消息";        // 群发消息标志
        public const string SERVER_IP = "192.168.1.112";    // 服务器 IP 地址
        public const int SERVER_PORT = 5000;                // 服务器端口号
        public readonly Type mType;                         // 协议类型

        /**
         * 构造方法。
         * @param type  协议类型
         */
        public ImProtocol(Type type) {
            mType = type;
        }
        
        /**
         * 将字节数组转换为协议。
         * @param bytes 字节数组
         * @return 协议 
         */
        public static ImProtocol FromBytes(byte[] bytes) {
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream(bytes);
            stream.Seek(0, SeekOrigin.Begin);
            return (ImProtocol)formatter.Deserialize(stream);
        }

        /**
         * 将协议转换为字节数组。
         * @param obj   协议
         * @return 字节数组
         */
        public static byte[] ToBytes(object obj) {
            BinaryFormatter formmatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            formmatter.Serialize(stream, obj);
            return stream.GetBuffer();
        }
    }

    // 添加好友请求
    [Serializable]
    public class AddFriendRequest: ImProtocol {
        public readonly string mDstUsername;    // 目标用户名
        public readonly int mSrcIconIndex;      // 源用户头像索引
        public readonly string mSrcUsername;    // 源用户名

        /**
         * 构造方法。
         * @param dstUsername   目标用户名
         * @param iconIndex     源用户头像索引
         * @param srcUsername   源用户名
         */
        public AddFriendRequest(string dstUsername, int srcIconIndex, string srcUsername): 
            base(Type.ADD_FRIEND_REQUEST) {
            mDstUsername = dstUsername;
            mSrcIconIndex = srcIconIndex;
            mSrcUsername = srcUsername;
        }
    }

    // 添加好友结果
    [Serializable]
    public class AddFriendResult: ImProtocol {
        public readonly int mDstIconIndex;      // 目标用户头像索引
        public readonly string mDstUsername;    // 目标用户名
        public readonly ResultCode mResultCode; // 结果码
        public readonly string mSrcUsername;    // 源用户名
         
        /**
         * 构造方法。
         * @param dstIconIndex  目标用户头像索引
         * @param dstUsername   目标用户名
         * @param resultCode    结果码
         * @param srcUsername   源用户名
         */
        public AddFriendResult(int dstIconIndex, string dstUsername, ResultCode resultCode, string srcUsername): 
            base(Type.ADD_FRIEND_RESULT) {
            mDstIconIndex = dstIconIndex;
            mDstUsername = dstUsername;
            mResultCode = resultCode;
            mSrcUsername = srcUsername;
        }
    }
    
    // 聊天信息
    [Serializable]
    public class ChatInfo: ImProtocol {
        public readonly string mContent;        // 内容
        public readonly string mDstUsername;    // 目标用户名
        public readonly string mSrcUsername;    // 源用户名
        public readonly string mTime;           // 生成时间

        /**
         * 构造方法。
         * @param content       内容
         * @param dstUsername   目标用户名
         * @param srcUsername   源用户名
         * @param time          生成时间
         */
        public ChatInfo(string content, string dstUsername , string srcUsername, string time): 
            base(Type.CHAT) {
            mContent = content;
            mDstUsername = dstUsername;
            mSrcUsername = srcUsername;
            mTime = time;
        }
    }

    // 好友登录通知
    [Serializable]
    public class FriendLogon: ImProtocol {
        public readonly string mUsername;   // 用户名

        /**
         * 构造方法。
         * @param username  用户名
         */
        public FriendLogon(string username): 
            base(Type.FRIEND_LOGON) {
            mUsername = username;
        }
    }

    // 离线请求
    [Serializable]
    public class LogoffRequest: ImProtocol {
        public readonly string mUsername;   // 用户名

        /**
         * 构造方法。
         * @param username  用户名
         */
        public LogoffRequest(string username): 
            base(Type.LOGOFF) {
            mUsername = username;
        }
    }

    // 登录请求
    [Serializable]
    public class LogonRequest: ImProtocol {
        public readonly UserInfo mUserInfo; // 用户信息

        /**
         * 构造方法。
         * @param password   密码
         * @param username   用户名
         */
        public LogonRequest(string password, string username): 
            base(Type.LOGON) {
            mUserInfo = new UserInfo(0, password, username);
        }
    }

    // 登录结果
    [Serializable]
    public class LogonResult: ImProtocol {
        public int mFriendCount;            // 好友数
        public List<UserInfo> mFriends;     // 好友列表
        public List<bool> mFriendsOnline;   // 好友在线状态列表
        public int mIconIndex;              // 头像索引
        public ResultCode mResultCode;      // 结果码

        /**
         * 构造方法。
         */
        public LogonResult(): 
            base(Type.LOGON) {
            // 初始化成员
            mFriendCount = 0;
            mIconIndex = -1;
            mResultCode = ResultCode.SUCCEEDED;
        }
    }

    // 注册请求
    [Serializable]
    public class RegRequest: ImProtocol {
        public readonly UserInfo mUserInfo; // 用户信息

        /**
         * 构造方法。
         * @param iconIndex 头像索引
         * @param password  密码
         * @param username  用户名
         */
        public RegRequest(int iconIndex, string password, string username): 
            base(Type.REG) {
            mUserInfo = new UserInfo(iconIndex, password, username);
        }
    }

    // 注册结果
    [Serializable]
    public class RegResult: ImProtocol {
        public ResultCode mResultCode;  // 结果码

        /**
         * 构造方法。
         */
        public RegResult(): 
            base(Type.REG) {
            mResultCode = ResultCode.SUCCEEDED;
        }
    }

    // 用户信息
    [Serializable]
    public class UserInfo {
        public readonly int mIconIndex;     // 头像索引
        public readonly string mPassword;   // 密码
        public readonly string mUsername;   // 用户名

        /**
         * 构造方法。
         * @param iconIndex 头像索引
         * @param password  密码
         * @param username  用户名
         */
        public UserInfo(int iconIndex, string password, string username) {
            mIconIndex = iconIndex;
            mPassword = password;
            mUsername = username;
        }
    }
}
